// types/global.d.ts
declare global {
  interface FileStreamOptions {
    bufferSize?: number;
    encoding?: BufferEncoding;
  }
}

export {};

// fileStream.ts
import { Readable, Writable } from 'node:stream';
import { promises as fs } from 'node:fs';
import path from 'node:path';

class FileStreamError extends Error {
  constructor(message: string, public code?: string) {
  super(message);
  this.name = 'FileStreamError';
}
}

class FileReadable extends Readable {
  private fd: number | null = null;
  private buffer: Buffer;
  private position: number = 0;

  constructor(
    private filename: string,
  private options: FileStreamOptions = {}
) {
  super(options);
  this.buffer = Buffer.alloc(options.bufferSize || 1024);
  this.open();
}

private async open(): Promise<void> {
  try {
    await this.checkReadPermission();
    this.fd = await fs.open(this.filename, 'r');
    this.emit('open');
    this.read();
  } catch (error) {
    this.emit('error', new FileStreamError(
      `无法打开文件 ${this.filename}: ${error.message}`,
      'FILE_OPEN_ERROR'
    ));
  }
}

private async checkReadPermission(): Promise<void> {
  try {
    await fs.access(this.filename, fs.constants.R_OK);
  } catch (error) {
    throw new FileStreamError(
      `文件 ${this.filename} 没有读权限`,
      'PERMISSION_ERROR'
    );
  }
}

private async read(): Promise<void> {
  if (!this.fd) return;

try {
  const { bytesRead } = await fs.read(
    this.fd,
    this.buffer,
    0,
    this.buffer.length,
    this.position
  );

  if (bytesRead === 0) {
    await fs.close(this.fd);
    this.push(null);
    return;
  }

  this.position += bytesRead;
  this.push(this.buffer.slice(0, bytesRead));
} catch (error) {
  await fs.close(this.fd);
  this.emit('error', new FileStreamError(
    `读取文件时发生错误: ${error.message}`,
    'READ_ERROR'
  ));
}
}

_read(): void {
  this.read();
}
}

class FileWritable extends Writable {
  private fd: number | null = null;

  constructor(
    private filename: string,
  private options: FileStreamOptions = {}
) {
  super(options);
  this.open();
}

private async open(): Promise<void> {
  try {
    await this.checkWritePermission();
    this.fd = await fs.open(this.filename, 'w');
    this.emit('open');
  } catch (error) {
    this.emit('error', new FileStreamError(
      `无法打开文件 ${this.filename}: ${error.message}`,
      'FILE_OPEN_ERROR'
    ));
  }
}

private async checkWritePermission(): Promise<void> {
  const dirPath = path.dirname(this.filename);
  try {
    await fs.access(dirPath, fs.constants.W_OK);
  } catch (error) {
    throw new FileStreamError(
      `目录 ${dirPath} 没有写权限`,
      'PERMISSION_ERROR'
    );
  }
}

async _write(
  chunk: Buffer,
  encoding: BufferEncoding,
  callback: (error?: Error | null) => void
): Promise<void> {
  if (!this.fd) {
  this.once('open', () => this._write(chunk, encoding, callback));
  return;
}

try {
  await fs.write(this.fd, chunk, 0, chunk.length, null);
  callback();
} catch (error) {
  callback(new FileStreamError(
    `写入文件时发生错误: ${error.message}`,
    'WRITE_ERROR'
  ));
}
}

async _final(callback: (error?: Error | null) => void): Promise<void> {
  if (!this.fd) {
  this.once('open', () => this._final(callback));
  return;
}

try {
  await fs.close(this.fd);
  callback();
} catch (error) {
  callback(new FileStreamError(
    `关闭文件时发生错误: ${error.message}`,
    'CLOSE_ERROR'
  ));
}
}
}

// 使用示例
async function copyFile(sourcePath: string, targetPath: string): Promise<void> {
  const readable = new FileReadable(sourcePath);
  const writable = new FileWritable(targetPath);

  return new Promise((resolve, reject) => {
    readable.on('error', (error) => {
      reject(error);
    });

    writable.on('error', (error) => {
      reject(error);
    });

    writable.on('finish', () => {
      resolve();
    });

    readable.pipe(writable);
  });
}

// 导出模块
export {
  FileReadable,
  FileWritable,
  copyFile,
  FileStreamError,
  FileStreamOptions
};